﻿/* dk2Repository - Copyright (C) 2011 Daniel Kuczewski http://www.dk2.de/

 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */

using dk2Database.Commands;
using dk2Repository.Interfaces;

namespace dk2Repository
{
    public abstract partial class Repository<T> : IResetable where T : class, new()
    {


        private readonly IChangeTracker _changeTracker;
        private EnumStatus _status;

        protected Repository()
        {
            _changeTracker = new HashCodeTracker(_mapping, this);
            _status = EnumStatus.New;
        }

        public EnumStatus Status
        {
            get
            {
                if (_status == EnumStatus.Unchanged && _changeTracker.HasChanged)
                {
                    _status = EnumStatus.Updated;
                    _changeTracker.Reset();
                }

                return _status;

            }
            set 
            { 
                _status = value; 
                _changeTracker.Reset();
            }
        }


        public ExecuteCommand InsertCommand
        {
            get
            {
                return _cmdFactory.CreateInsert(this as T);
            }
        }

        public ExecuteCommand UpdateCommand
        {
            get
            {
                return _cmdFactory.CreateUpdate(this as T);
            }
        }

        public ExecuteCommand DeleteCommand
        {
            get
            {
                return _cmdFactory.CreateDelete(this as T);
            }
        }

        public bool Save()
        {
            switch (Status)
            {
                case EnumStatus.Updated:
                    return Update();
                case EnumStatus.New:
                    Insert();
                    return true;
            }

            return false;
        }

        public bool Update()
        {
            BeforeUpdate();
            var b = Update(this as T);
            if (b)
                AfterUpdate();

            return b;
        }

        protected virtual void BeforeUpdate() { }
        protected virtual void AfterUpdate()
        {
            Reset();
        }

        public void Insert()
        {
            BeforeInsert();
            Insert(this as T);
            AfterInsert();
        }

        protected virtual void BeforeInsert() {}
        protected virtual void AfterInsert()
        {
            Reset();
        }

        public bool Delete()
        {
            BeforeDelete();
            var b = Delete(this as T);
            if (b)
            {
                AfterDelete();
            }

            return b;

        }

        protected virtual void BeforeDelete() {}
        protected virtual void AfterDelete()
        {
            Status = EnumStatus.Deleted;            
        }

        public void Reset()
        {
            _changeTracker.Reset();
            _status =  EnumStatus.Unchanged;
        }
    }
}